package top.wyloop.fasthome.module.system.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import top.wyloop.fasthome.exception.SystemException;
import top.wyloop.fasthome.logger.ServiceLog;
import top.wyloop.fasthome.logger.SimpleServiceLog;
import top.wyloop.fasthome.module.system.model.entity.Home;
import top.wyloop.fasthome.module.system.model.entity.User;
import top.wyloop.fasthome.module.system.repository.HomeRepository;
import top.wyloop.fasthome.module.system.repository.UserRepository;
import top.wyloop.fasthome.module.system.service.HomeService;
import top.wyloop.fasthome.module.system.service.UserService;
import top.wyloop.fasthome.util.PasswordUtil;

import java.util.Date;
import java.util.Optional;

/**
 * @author Wyatt6
 * @date 2025/5/13
 */
@Slf4j
@Service
public class HomeServiceImpl implements HomeService {
    private static final String PASSWORD_REGEXP = "^[0-9]{6}$";

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private HomeRepository homeRepository;
    @Autowired
    private UserService userService;

    @Override
    @SimpleServiceLog("检查口令格式服务")
    public boolean checkPasswordFormat(String password) {
        return password.matches(PASSWORD_REGEXP);
    }

    @Override
    @ServiceLog("创建家庭服务")
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public Home createHome(Long adminId, String name, String password) {
        Assert.notNull(adminId, "管理员ID为空");
        Assert.hasText(name, "家庭名称为空");
        Assert.hasText(password, "口令为空");

        log.info("检查用户是否存在，且未绑定家庭");
        Optional<User> admin = userRepository.findById(adminId);
        if (admin.isEmpty() || admin.get().getHomeId() != null) {
            throw new SystemException("已绑定家庭");
        }

        log.info("口令格式校验并加密");
        if (!checkPasswordFormat(password)) {
            throw new SystemException("口令格式错误");
        }
        String salt = PasswordUtil.generateSalt();
        String encryptedPassword = PasswordUtil.encode(password, salt);

        Home record = new Home();
        record.setAdminId(adminId);
        record.setName(name);
        record.setPassword(encryptedPassword);
        record.setSalt(salt);
        record.setCreateTime(new Date());
        Home home = homeRepository.save(record);
        log.info("成功创建新家庭: id=[{}]", home.getId());

        User data = new User();
        data.setId(adminId);
        data.setHomeId(home.getId());
        userService.updateUserAttributesByIdRepeatableRead(data);
        log.info("成功更新管理员绑定的家庭ID");

        // 注意：JPA框架save持久化并不是即时写入数据库的，
        // 因此脱敏是不能在原对象上赋值为null，
        // 否则定义为非空的属性会报错。
        log.info("新家庭数据脱敏后返回");
        Home result = new Home();
        result.setId(home.getId());
        result.setAdminId(home.getAdminId());
        result.setName(home.getName());
        result.setCreateTime(home.getCreateTime());
        return result;
    }

    @Override
    @ServiceLog("更换口令服务")
    public void changePassword(Long adminId, String password) {
        Assert.notNull(adminId, "管理员ID为空");
        Assert.hasText(password, "新口令为空");
        log.info("输入参数: adminId=[{}]", adminId);

        log.info("新口令格式校验并加密");
        if (!checkPasswordFormat(password)) {
            throw new SystemException("新口令格式错误");
        }

        Home home = homeRepository.findByAdminId(adminId);
        if (home == null) {
            throw new SystemException("仅家庭管理员可以更换口令");
        } else {
            String salt = PasswordUtil.generateSalt();
            String encryptedPassword = PasswordUtil.encode(password, salt);
            home.setPassword(encryptedPassword);
            home.setSalt(salt);

            log.info("更新数据库记录");
            homeRepository.save(home);
        }
    }
}
